import CryptoJS from "crypto-js"
import {fetchEventSource} from "@microsoft/fetch-event-source"

export class AppApi {
    private static token: string
    private static readonly baseUrl: string = import.meta.env.VITE_API_BASE_URL
    private static readonly appSecret = import.meta.env.VITE_APP_SECRET
    private static readonly appKey = import.meta.env.VITE_APP_KEY

    static async login(username: string) {
        const ticketUrl = "/api/v1/freeLogin"
        const ticketParam = {username: username}
        const ticketData = await this.post(ticketUrl, ticketParam, {
            "X-App-Key": this.appKey,
            "X-Signature": this.getSignCode(ticketUrl, ticketParam),
        })
        const ticket = ticketData.token
        const loginUrl = "/api/v1/loginWithTicket"
        const loginParam = {ticket: ticket}
        const loginData = await this.post(loginUrl, loginParam, {
            "X-App-Key": this.appKey,
            "X-Signature": this.getSignCode(loginUrl, loginParam),
        })
        this.token = loginData.token
    }

    static async getAppInfo(appId: string, type: string) {
        return this.get(`/api/v1/apps/${appId}/${type}`)
    }

    static async restart(appId: string, contextId: string, params:any,onMessage: (message: any) => void) {
        const url = `/api/v1/app/run/repeat/${appId}/${contextId}/rag`
        return this.fetchStream(url, params, {}, onMessage)
    }


    static async chat(appId: string, params: any, onMessage: (message: any) => void) {
        const url = `/api/v1/app/run/${appId}/rag`
        return this.fetchStream(url, params, {}, onMessage)
    }

    static async stopChat(appId: string,contextId: string) {
        const url = `/api/v1/context/${appId}/${contextId}/0/stop`
        return this.get(url)
    }

    static async deleteContext(appId: string,contextId: string) {
        return this.delete(`/api/v1/context/${appId}/${contextId}`)
    }

    static async getChatHistory(appId: string) {
      // return this.get(`/api/v1/chatHistory?page=1&size=10&appId=${appId}&deleted=false`)
        return this.get(
            `/api/v1/context/${appId}?size=10`
        );
    }
    static async getChatHistoryDetail(appId: string) {
        return this.get(
            `/api/v1/context/chat/${appId}`
        );
    }

    static async get(url: string, headers?: any) {
        const res = await globalThis.fetch(this.baseUrl + url, {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${this.token || ""}`,
                ...headers,
            },
        })
        const response: any = await res.json()
        if (response.code == 0) {
            return response.result
        }
        return Promise.reject(response.message)
    }

    static async post(url: string, params: any, headers: any) {
        const res = await globalThis.fetch(this.baseUrl + url, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${this.token || ""}`,
                ...headers,
            },
            body: JSON.stringify(params),
        })
        const response: any = await res.json()
        if (response.code == 0) {
            return response.result
        }
        return Promise.reject(response.message)
    }

    static async delete(url: string, headers?: any) {
        const res = await globalThis.fetch(this.baseUrl + url, {
            method: "DELETE",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${this.token || ""}`,
                ...headers,
            },
        })
        const response: any = await res.json()
        if (response.code == 0) {
            return response.result
        }
        return Promise.reject(response.message)
    }

    static async fetchStream(
        url: string,
        params: any,
        headers: any,
        onMessage: (message: any) => void,
        method: string = 'POST'
    ) {
        await fetchEventSource(this.baseUrl + url, {
            method: method,
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${this.token || ""}`,
                ...headers,
            },
            body: method == 'POST' ? JSON.stringify(params) : null,
            onmessage(msg: any) {
                try {
                    const message = JSON.parse(msg.data)
                    onMessage(message)
                } catch (e: any) {
                    globalThis.console.error(e)
                }
            },
            onerror(err: any) {
                throw err
            },
        })
    }

    static getSignCode(url: string, data: any) {
        const dataForSign = this.appKey + url + JSON.stringify(data)
        const hmac = CryptoJS.HmacSHA256(dataForSign, AppApi.appSecret)
        return CryptoJS.enc.Base64.stringify(hmac)
    }
}
